#include "TaskManager.h"

#include <string.h>	// declares NULL
#include <stdio.h> // printf
#include "common.h"

#ifdef _WIN32
#ifdef _DEBUG
   #include <crtdbg.h>
   #undef THIS_FILE
   static char THIS_FILE[] = __FILE__;
   #define new       new( _NORMAL_BLOCK, __FILE__, __LINE__)
   #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif

// Constructor
TaskManager::TaskManager() {
#ifdef _DEBUG
	int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
	_CrtSetDbgFlag( tmpFlag );
#endif /* _DEBUG */

	// blank out link list of tasks
	this->head = this->curr = NULL;

	// initialize the mutex
	this->mutex = CreateMutex(NULL, FALSE, LPCTSTR("hMysql"));
}

// Deconstructor
TaskManager::~TaskManager() {
	// delete remaining tracked tasks
	clear();
}

// dete all saved tasks
void TaskManager::clear() {
	Task *slider = this->head;
	Task *tmp;

	// loop through tasks freeing each one in turn
	while(slider != NULL) {
		tmp = slider;
		slider = slider->next;
		delete[] tmp->id;	tmp->id = NULL;	// must be set to null, otherwise ~Task will try to delete
		delete tmp;
	}

	this->head = NULL;
}

// add a new task
Task* TaskManager::add(char *id, State state) {
	Task *slider;

	// don't add again if already exists
	slider = this->get(id);
	if(slider != NULL) {
		slider->state = state;	// set the provided status
		return slider;
	}

	// initialize slider at head
	slider = this->head;

	// this will be the first task
	if(slider == NULL) {
		this->head = new Task;
		this->head->prev = NULL;
		this->head->next = NULL;

		slider = this->head;
	}
	// not the first task, add to end of list
	else {
		// advanced till slider is the last node
		while(slider->next != NULL) {
			slider = slider->next;
		}
		// at end of list, attach new task
		slider->next = new Task;
		slider->next->prev = slider;
		slider->next->next = NULL;

		slider = slider->next;
	}

	// set initial values
	//slider->id = _strdup(id);
	slider->id = new char[strlen(id) + 1];
	strcpy(slider->id, id);
	slider->state = state;

	// return pointer to new task
	return slider;
}

// del a task by the specified id
bool TaskManager::del(char *id) {
	Task *slider = this->head;

//	printf("[TaskManager::del]\r\n");

	if(slider == NULL) {
		return false;
	}

	while(slider != NULL) {
		if(!strcmp(slider->id, id)) {
			break;
		}
		slider = slider->next;
	}

	if(slider == NULL) {
		return false;
	}

	if(slider->prev) {
		if(slider->next) {
			slider->prev->next = slider->next;
		}
		else {
			slider->prev->next = NULL;
		}
	}
	if(slider->next) {
		if(slider->prev) {
			slider->next->prev = slider->prev;
		}
		else {
			slider->next->prev = NULL;
		}
	}
	if(slider == this->head) {
		this->head = slider->next;
		if(this->head) {
			this->head->prev = NULL;
		}
	}
	if(slider == this->curr) {
		this->curr = slider->next;
	}

	delete[] slider->id;	slider->id = NULL;
	delete slider;

	return true;
}


// get a task by the specified id
Task* TaskManager::get(char *id) {
	Task *slider = this->head;

//	printf("[TaskManager::get]: %d\r\n", id);

	// loop through each task
	while(slider != NULL) {
		// check if this is the task we are looking for
		if(!strcmp(slider->id, id)) {
			return slider;
		}

		// advanced till slider to next node
		slider = slider->next;
	}

	return NULL;
}

// set a task detail
bool TaskManager::set(char *id, char *data, char *value) {
	Task *task = this->get(id);
	if(task == NULL) {
		return false;
	}

	// save the detail
	task->pm.set(data, value);

	return true;
}


// reset current pointer back to head node
Task* TaskManager::reset() {
	this->curr = this->head;
	return this->curr;
}

// return current task pointer and advance forward
Task* TaskManager::getNext() {
	// advance to next task and return, null returned if at end of list
	if(this->curr) {
		this->curr = this->curr->next;
	}

	return this->curr;
}

// return current pointer and advance backward
Task* TaskManager::getPrev() {
	// advance to prev task and return, null returned if at end of list
	if(this->curr) {
		this->curr = this->curr->prev;
	}

	return this->curr;
}

void TaskManager::dump() {
	Task *slider = this->head;
	char data[DEFAULT_BUFLEN];

	while(slider != NULL) {
		sprintf(data, "task_list|id=%s|priority=%s|state=%d\n",
			slider->id, slider->pm.get("priority"), slider->state);
		printf("%s", data);

		slider = slider->next;
	}
}